import Axios, {
  AxiosInstance,
  AxiosRequestConfig,
  CustomParamsSerializer,
} from "axios";
import {
  PureHttpError,
  RequestMethods,
  PureHttpResponse,
  PureHttpRequestConfig,
} from "./types.d";
import { stringify } from "qs";
import {
  getUserLoginInfo,
  removeUserLoginInfo,
  removeStorageLong,
  getUserToken
} from "./auth";
import { ElMessage } from "element-plus";
import crypto from '@/utils/crypto'

import router from "@/router/index";
const { VITE_API_URL, VITE_TEST_TOKEN } = import.meta.env;
// 相关配置请参考：www.axios-js.com/zh-cn/docs/#axios-request-config-1
const defaultConfig: AxiosRequestConfig = {
  // 请求超时时间
  timeout: 15000,
  headers: {
    Accept: "application/json, text/plain, */*",
    "Content-Type": "application/json",
    "X-Requested-With": "XMLHttpRequest",
  },
  // 数组格式参数序列化（https://github.com/axios/axios/issues/5142）
  paramsSerializer: {
    serialize: stringify as unknown as CustomParamsSerializer,
  },
};

class PureHttp {
  constructor() {
    this.httpInterceptorsRequest();
    this.httpInterceptorsResponse();
  }

  /** token过期后，暂存待执行的请求 */
  private static requests = [];

  /** 防止重复刷新token */
  private static isRefreshing = false;

  /** 初始化配置对象 */
  private static initConfig: PureHttpRequestConfig = {};

  /** 保存当前Axios实例对象 */
  private static axiosInstance: AxiosInstance = Axios.create(defaultConfig);

  /** 重连原始请求 */
  private static retryOriginalRequest(config: PureHttpRequestConfig) {
    return new Promise((resolve) => {
      PureHttp.requests.push((token: string) => {
        config.headers["Authorization"] = token;
        resolve(config);
      });
    });
  }

  /** 请求拦截 */
  private httpInterceptorsRequest(): void {
    PureHttp.axiosInstance.interceptors.request.use(
      async (config: PureHttpRequestConfig): Promise<any> => {
        config.headers["Type"] = 'QUVT';
        config.headers["Authorization"] = `bearer ${getUserToken() || VITE_TEST_TOKEN}`
        config.data = config.data && { dataSrc: crypto.Encrypt(JSON.stringify(config.data)) }
        return config
        // 开启进度条动画
        // if (!config.hideLoading) NProgress.start();
        // 优先判断post/get等方法是否传入回掉，否则执行初始化设置等回掉
        if (typeof config.beforeRequestCallback === "function") {
          config.beforeRequestCallback(config);
          return config;
        }
        if (PureHttp.initConfig.beforeRequestCallback) {
          PureHttp.initConfig.beforeRequestCallback(config);
          return config;
        }
        /** 请求白名单，放置一些不需要token的接口（通过设置请求白名单，防止token过期后再请求造成的死循环问题） */
        const whiteList = ["/publicKey", "/token/refresh", "/login"];
        return whiteList.some((v) => config.url.indexOf(v) > -1)
          ? config
          : new Promise((resolve) => {
            const data = getUserLoginInfo();
            if (data) {
              const { tokenData } = data;
              const now = new Date().getTime();
              const expired = parseInt(tokenData?.expires_in) - now <= 0;
              if (expired) {
                if (!PureHttp.isRefreshing) {
                  PureHttp.isRefreshing = true;
                  // *****TODO：待完善*****调用refreshToken接口，重新更新token，然后将PureHttp.isRefreshing设置为false
                  PureHttp.isRefreshing = false;
                }
                resolve(PureHttp.retryOriginalRequest(config));
              } else {
                // config.headers["Authorization"] = tokenData.access_token;
                resolve(config);
              }
            } else {
              resolve(config);
            }
          });
      },
      (error) => {
        return Promise.reject(error);
      },
    );
  }

  /** 响应拦截 */
  private httpInterceptorsResponse(): void {
    const instance = PureHttp.axiosInstance;
    instance.interceptors.response.use(
      (response: PureHttpResponse) => {
        const $config = response.config;
        // 关闭进度条动画
        // NProgress.done();
        // 优先判断post/get等方法是否传入回掉，否则执行初始化设置等回掉
        if (typeof $config.beforeResponseCallback === "function") {
          $config.beforeResponseCallback(response);
          return response.data;
        }
        if (PureHttp.initConfig.beforeResponseCallback) {
          PureHttp.initConfig.beforeResponseCallback(response);
          return response.data;
        }

        // 如果不是我们服务的接口，直接返回这个数据结构，不解析业务状态码
        if (response?.config?.url?.indexOf(VITE_API_URL) === -1) {
          return response.data;
        }
        switch (response.data.errCode) {
          case "200": {
            try {
              let newData = response.data.result
              if (newData)
                return newData && JSON.parse(crypto.Decrypt(newData))
              else
                return newData
            } catch (err) {
              return (response.data.result || response.data.data) || response
            }
          }
          default: {
            ElMessage({
              message: response.data.errMsg,
              type: "error",
            });
            return Promise.reject(response.data);
          }
        }
      },
      (error: PureHttpError) => {
        const $error = error;
        $error.isCancelRequest = Axios.isCancel($error);
        // 所有的响应异常 区分来源为取消请求/非取消请求
        return Promise.reject($error);
      },
    );
  }

  /** 通用请求工具函数 */
  public request<T>(
    method: RequestMethods,
    url: string,
    param?: AxiosRequestConfig,
    axiosConfig?: PureHttpRequestConfig,
  ): Promise<T> {
    const config = {
      method,
      url: url.startsWith("http") ? url : VITE_API_URL + url,
      ...param,
      ...axiosConfig,
    } as PureHttpRequestConfig;
    // 单独处理自定义请求/响应回掉
    return new Promise((resolve, reject) => {
      PureHttp.axiosInstance
        .request(config)
        .then((response: undefined) => {
          resolve(response);
        })
        .catch((error) => {
          if (error?.code == "ERR_NETWORK") {
            ElMessage({
              message: "网络异常，请确认网路连接是否正常",
              type: "error",
            });
          }
          if (error?.response?.status && error?.response?.status >= 500) {
            ElMessage({
              message:
                error.response.status === 504
                  ? "请求超时，请稍后再试"
                  : "服务器异常，请稍后再试",
              type: "error",
            });
          }
          reject(error);
        });
    });
  }

  /** 单独抽离的post工具函数 */
  public post<T, P>(
    url: string,
    params?: AxiosRequestConfig<T>,
    config?: PureHttpRequestConfig,
  ): Promise<P> {
    return this.request<P>("post", url, params, config);
  }

  /** 单独抽离的get工具函数 */
  public get<T, P>(
    url: string,
    params?: AxiosRequestConfig<T>,
    config?: PureHttpRequestConfig,
  ): Promise<P> {
    return this.request<P>("get", url, params, config);
  }
}

export const http = new PureHttp();

export interface BaseResponse<T = undefined> {
  [x: string]: never[];
  code: string;
  msg: string;
  status: boolean;
  data?: T;
}
